package com.deploy.util;

import com.deploy.model.ServerInfo;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SSH连接工具类
 * 负责创建和管理SSH连接
 */
@Slf4j
public class SSHUtil {
    private static final int DEFAULT_TIMEOUT = 60000; // 默认超时时间60秒

    /**
     * 创建SSH连接
     *
     * @param serverInfo 服务器信息
     * @return JSch Session对象
     */
    public static Session createSession(ServerInfo serverInfo) throws JSchException {
        // 正在连接服务器
        log.info("正在连接服务器: {}", serverInfo.getIp());
        // 创建一个Jsch 对象
        JSch jSch = new JSch();
        // 创建一个会话
        Session session = jSch.getSession(serverInfo.getUsername(), serverInfo.getIp(), serverInfo.getPort());
        // 设置会话的密码
        session.setPassword(serverInfo.getPassword());
        // 设置连接属性
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no"); // 不检查主机秘钥
        // 设置配置信息
        session.setConfig(config);
        // 设置超时
        session.setTimeout(DEFAULT_TIMEOUT);
        // 连接服务器
        session.connect();
        // 连接到服务器
        log.info("成功连接到服务器：{}", serverInfo.getIp());
        // 设置session
        return session;
    }

    /**
     * 执行远程命令
     *
     * @param session SSH会话
     * @param command 要执行的命令
     * @return 命令执行结果
     */
    public static String executeCommand(Session session, String command) throws JSchException, IOException {
        // 执行命令
        log.info("执行命令：{}", command);
        // 创建一个命令的执行通道
        ChannelExec channel = null;
        // 创建一个StringBuilder
        StringBuilder output = new StringBuilder();
        // try-finally
        try {
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command);
            // 得到输入流
            InputStream in = channel.getInputStream();
            channel.connect();

            byte[] tmp = new byte[1024];
            while (true) {
                while (in.available() > 0) {
                    int i = in.read(tmp, 0, 1024);
                    if (i < 0) break;
                    output.append(new String(tmp, 0, i));
                }
                if (channel.isClosed()) {
                    if (in.available() > 0) continue;
                    log.info("命令执行完成，退出状态: {}", channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(100);
                } catch (Exception ee) {
                    // 忽略中断异常
                    ee.printStackTrace();
                }
            }
        }finally {
            if (channel != null){
                channel.disconnect();
            }
        }
        return output.toString();
    }

    /**
     * 检测远程服务器操作系统类型
     *
     * @param session SSH会话
     * @return 操作系统类型
     */
    public static ServerInfo.OsType detectOsType(Session session) {
        try {
            String linuxResult = executeCommand(session, "uname -a");
            if (linuxResult.toLowerCase().contains("linux")) {
                log.info("检测到Linux操作系统");
                return ServerInfo.OsType.LINUX;
            } else {
                log.info("检测到Windows操作系统");
                return ServerInfo.OsType.WINDOWS;
            }
        } catch (Exception e) {
            log.warn("检测操作系统类型失败，默认使用Linux：{}", e.getMessage());
            // 默认使用Linux
            return ServerInfo.OsType.LINUX;
        }
    }

    /**
     * 关闭SSH会话
     *
     * @param session SSH会话
     */
    public static void closeSession(Session session) {
        // 关闭session
        if (session != null && session.isConnected()) {
            session.disconnect();
            log.info("已关闭SSH连接");
        }
    }
}
